#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <set>
#include "Log.hpp"
using namespace std;

const string sep=" ";
class Command
{
private:
    bool LoadConf(string cond_path)
    {
        std::ifstream in(cond_path);
        if (!in.is_open())
        {
            LOG(FATAL, "open %s error\n", cond_path.c_str());
            return false;
        }
        std::string line;
        while (std::getline(in, line))
        {
            LOG(DEBUG, "load [%s] success\n", line.c_str());
            _safe_cmd.insert(line);
        }
        in.close();

        return true;
    }

public:
    Command(const string &cond_path) : _cond_path(cond_path)
    {
        LoadConf(_cond_path);
    }
    string PrefixCommand(string cmd)
    {
        if(cmd.empty()) return string();
        auto pos=cmd.find(sep);
        if(pos==string::npos)
        {
            return cmd;
        }
        else
        {
            return cmd.substr(0,pos);
        }
    }
    bool SafeCheck(string cmd)
    {
        string prefix=PrefixCommand(cmd);
        auto iter = _safe_cmd.find(prefix);
        if (iter == _safe_cmd.end())
        {
            return false;
        }
        return true;
    }
    string Excute(const string &cmd)
    {
        string result;
        if (SafeCheck(cmd))
        {
            // p=pipe;底层创建一个管道
            FILE *fp = popen(cmd.c_str(), "r");
            if (fp == nullptr)
            {
                return "failed";
            }
            char buffer[1024];
            while (fgets(buffer, sizeof(buffer), fp) != nullptr)
            {
                result += buffer;
            }
            pclose(fp);
        }
        else
        {
            result = "非法！\n";
        }
        return result;
    }
    ~Command()
    {
    }

private:
    set<string> _safe_cmd;
    string _cond_path;
};
